package priv.blackbibo.application.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.net.SocketKeepalive;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.temporal.Temporal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import priv.blackbibo.application.R;

public class BLEActivity extends AppCompatActivity {

    private static final String TAG = "BLEActivity";

    private ListView bles = null;
    private ListAdapter blesAdapter = null;
    private List<Map<String, String>> mData = new LinkedList<>();
    private BluetoothAdapter bluetoothAdapter;
    private UUID uuid = null;

    private AcceptThread acceptThread = null;
    private ConnectThread connectThread = null;
    private BluetoothDevice selectDeivce = null;

    private Handler handler = new Handler();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble);

        Log.d(TAG, "onCreate: init");

        uuid = UUID.fromString("ad2008f2-1ef5-11ea-ae33-0221860e9b7e");

        bles = findViewById(R.id.bles);
        blesAdapter = new SimpleAdapter(this,mData,R.layout.ble_item,new String[]{"name","macaddress"},new int[]{R.id.name,R.id.macAddress});
        bles.setAdapter(blesAdapter);
        bles.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                TextView macAddress = view.findViewById(R.id.macAddress);
                String mac = macAddress.getText().toString();

                Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
                for (BluetoothDevice device : pairedDevices) {
                    if (device.getAddress().equals(mac)) {
                        selectDeivce = device;
//                        uuid = device.getUuids()[1].getUuid();
                        break;
                    }
                }

                RadioGroup radioGroup = findViewById(R.id.radio_mode);
                int checkedId = radioGroup.getCheckedRadioButtonId();
                switch (checkedId) {
                    case R.id.server:
                        alert("开启服务端");
                        acceptThread = new AcceptThread(mac);
                        acceptThread.start();
                        break;
                    case R.id.client:
                        alert("开启客户端");
                        connectThread = new ConnectThread();
                        connectThread.start();
                        break;
                        default:
                            alert("请选择服务类型");
                }
            }
        });

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            alert("未找到蓝牙设备");
            return;
        }
        if (!bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, 1);
            alert("蓝牙未开启");
            return;
        }

        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();

        if (pairedDevices.size() > 0) {
            // There are paired devices. Get the name and address of each paired device.
            for (BluetoothDevice device : pairedDevices) {
                String deviceName = device.getName();
                String deviceHardwareAddress = device.getAddress(); // MAC address
                Map<String, String> ble = new HashMap<>();
                ble.put("name",deviceName);
                ble.put("macaddress", deviceHardwareAddress);
                mData.add(ble);
            }
        }else {
            alert("没有发现可用的设备");
        }
    }

    public void alert(String message){
        Log.d(TAG, "alert: " + message);
    }

    private class AcceptThread extends Thread {
        private BluetoothServerSocket mmServerSocket = null;

        public AcceptThread(String mac) {
            // Use a temporary object that is later assigned to mmServerSocket
            // because mmServerSocket is final.
            BluetoothServerSocket tmp = null;
            try {
                // MY_UUID is the app's UUID string, also used by the client code.
                Log.d(TAG, "AcceptThread: " + uuid.toString());
                tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("01",uuid);
            } catch (IOException e) {
                alert("Socket's listen() method failed");
            }
            mmServerSocket = tmp;
        }



        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned.
            while (true) {
                try {
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    alert("服务开启失败");
                    break;
                }
                alert("连接成功");
                if (socket != null) {
                    // A connection was accepted. Perform work associated with
                    // the connection in a separate thread.
                    serverSideManager(socket);
                    try {
                        mmServerSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }

        // Closes the connect socket and causes the thread to finish.
        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                alert("Could not close the connect socket");
            }
        }
    }

    private class ConnectThread extends Thread {
        private BluetoothSocket mmSocket;
        private BluetoothDevice mmDevice;

        public ConnectThread() {
            // Use a temporary object that is later assigned to mmSocket
            // because mmSocket is final.
            BluetoothSocket tmp = null;
            mmDevice = selectDeivce;

            try {
                // Get a BluetoothSocket to connect with the given BluetoothDevice.
                // MY_UUID is the app's UUID string, also used in the server code.
                Log.d(TAG, "ConnectThread: " + uuid.toString());
                tmp = selectDeivce.createInsecureRfcommSocketToServiceRecord(uuid);
            } catch (IOException e) {
                alert("Socket's create() method failed");
            }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it otherwise slows down the connection.
            bluetoothAdapter.cancelDiscovery();

            try {
                // Connect to the remote device through the socket. This call blocks
                // until it succeeds or throws an exception.m
                mmSocket = selectDeivce.createInsecureRfcommSocketToServiceRecord(uuid);
                mmSocket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and return.
                Log.d("ble", "connect fial",connectException);
                alert("链接服务端失败");
                try {
                    mmSocket.close();
                } catch (IOException closeException) {
                    alert("Could not close the client socket");
                }
                return;
            }

            // The connection attempt succeeded. Perform work associated with
            // the connection in a separate thread.
            clientSidemanager(mmSocket);
        }

        // Closes the client socket and causes the thread to finish.
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                alert("Could not close the client socket");
            }
        }
    }

    private void serverSideManager(BluetoothSocket socket){
        try {
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            byte[] message = "hello".getBytes();
            byte[] words = Arrays.copyOf(message,1024);
            outputStream.write(words);
            outputStream.flush();

            inputStream.read(words);
            alert(new String(words));
//            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void clientSidemanager(BluetoothSocket socket){
        try {
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            byte[] words = new byte[1024];
            inputStream.read(words);
            outputStream.write(Arrays.copyOf("back".getBytes(),1024));
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (acceptThread != null) {
            acceptThread.cancel();
        }
        if (connectThread != null) {
            connectThread.cancel();
        }
    }
}
